Add func-operator integration to deploy command #3657
Add func-operator integration to deploy command #3657creydr wants to merge 13 commits intoknative:mainfrom
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: creydr The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #3657 +/- ##
==========================================
- Coverage 56.91% 56.70% -0.21%
==========================================
Files 181 184 +3
Lines 20928 21291 +363
==========================================
+ Hits 11911 12074 +163
- Misses 7810 7988 +178
- Partials 1207 1229 +22
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
6bd73c4 to
ba2e1c9
Compare
lkingland
left a comment
There was a problem hiding this comment.
Looks great! My only substantive suggestion is that this be integrated more deeply into core instead of an ad-hoc post-deploy hook 👍🏻
| module knative.dev/func | ||
|
|
||
| go 1.25.9 | ||
| go 1.26 |
There was a problem hiding this comment.
I presume this was necessary due to controller-runtime dependency? Maybe just add to the commit description this PR also bumps to Go 1.26
There was a problem hiding this comment.
Yes, required by controller-runtime. Added a note to the PR description.
| } | ||
|
|
||
| if cfg.RepoURL == "" { | ||
| fmt.Fprintln(os.Stderr, "Function CR not created: no git remote found. Set --git-url to enable operator management.") |
There was a problem hiding this comment.
This warning will fire on every deploy without a configured git remote, given --manage=true is the default. I think that there are actually two preconditions for a Function to be "managed": The operator is installed AND they're using git.
The base case: A user just initializes a function and deployes it directly to a vanilla cluster, shouldn't really even print a warning (it's an expected base case).
There was a problem hiding this comment.
Good point. Changed to skip silently when no git remote is configured — the two preconditions are now operator CRD installed AND git URL available.
| } | ||
|
|
||
| if existing != nil { | ||
| existing.Spec = desiredSpec |
There was a problem hiding this comment.
Just double-checking: without using a merge, this will always overwrite the spec, even if changed in some different way. I think that's what we want (again encouraging declarative config), but just want to flag this to be sure.
There was a problem hiding this comment.
Correct, this is intentional. The spec is always overwritten with the local state to encourage declarative config.
| func hasFunctionCRD(disc discovery.DiscoveryInterface) (bool, error) { | ||
| resources, err := disc.ServerResourcesForGroupVersion("functions.dev/v1alpha1") | ||
| if err != nil { | ||
| return false, nil |
There was a problem hiding this comment.
This swallows any error from ServerResourcesForGroupVersion and treats it identically to "CRD not present." If there's a legitimate reason, we probably want to raise an error. Perhaps something like:
resources, err := disc.ServerResourcesForGroupVersion("functions.dev/v1alpha1")
if err != nil {
if apierrors.IsNotFound(err) || meta.IsNoMatchError(err) {
return false, nil
}
return false, fmt.Errorf("checking for Function CRD: %w", err)
}(I haven't fully traced the call path here; just an example)
There was a problem hiding this comment.
Fixed. Now only IsNotFound errors are treated as CRD absence; other errors are propagated.
| if list.Items[i].Status.Name == funcName { | ||
| return &list.Items[i], nil | ||
| } | ||
| } | ||
|
|
||
| for i := range list.Items { | ||
| if list.Items[i].Name == funcName { |
There was a problem hiding this comment.
Minor nit: these two loops over list.Items made me double-check to see if it was an error. maybe just put both if statements in one for-loop for clarity that this was intended.
There was a problem hiding this comment.
Combined into a single loop. Status name match still takes priority (returns immediately); metadata name match is remembered as fallback.
| if c.Manage { | ||
| o = append(o, fn.WithPostDeploy(func(ctx context.Context, f fn.Function) error { | ||
| if err := syncFunctionCR(ctx, f, c, creds); err != nil { | ||
| fmt.Fprintf(os.Stderr, "Warning: failed to sync Function CR: %v\n", err) | ||
| } | ||
| return nil | ||
| })) | ||
| } |
There was a problem hiding this comment.
This should probably be part of core rather than in the CLI. Adding a boolean to the Function structh which states this is a "managed" Function, and a CR should be created (if the operator is installed).
There was a problem hiding this comment.
Done. Moved into core Client.Deploy() via a FunctionSyncer interface, with ManagementDisabled field on DeploySpec (managed by default).
| pipelinesProvider PipelinesProvider // CI/CD pipelines management | ||
| mcpServer MCPServer // MCP Server | ||
| startTimeout time.Duration // default start timeout for all runs | ||
| postDeploy func(context.Context, Function) error |
There was a problem hiding this comment.
No need for a post-deploy hook if we just extend the core's "deploy" logic to do the CR work if the given function is a "managed" function.
To make it even simpler, the flag could be "ManagementDisabled", such that the deafult will always be to create the CR if the system detects the operator is installed.
There was a problem hiding this comment.
Done. Replaced postDeploy hook with FunctionSyncer interface. --manage flag replaced by --management-disabled.
When deploying a function, automatically create or update a Function CR (functions.dev/v1alpha1) if the func-operator CRD is installed on the cluster. On first deploy, the CR is created with the git repository URL, branch, and path. On subsequent deploys, only the functions.knative.dev/last-deployed annotation is updated. - Add pkg/git/ with go-git based resolution of remote URL and branch - Add pkg/operator/ with Function CR sync logic and k8s client setup - Add WithPostDeploy client option to run post-deploy hooks - Add --manage flag (default true) to opt out with --manage=false - Wire operator sync via WithPostDeploy in deploy command - Git URL cascade: --git-url > tracking remote > origin - Branch cascade: --git-branch > current branch > "main" - Silently skip if CRD not installed; warn if no git remote found
Add TestInt_OperatorSync to the shared deployer integration test helper. The test deploys a function with WithPostDeploy wired to operator.SyncFunctionCR, verifies the Function CR is created with the correct spec on first deploy, and confirms only the last-deployed annotation is updated on subsequent deploys. CR verification is skipped gracefully when the Function CRD is not installed.
Add func-operator v0.2.1 to the cluster setup script so the Function CRD is available for integration tests. The operator is installed in parallel with other components during cluster allocation.
ResolveRemoteURL now removes userinfo (username and password) from HTTP/HTTPS remote URLs before returning them, preventing credentials from being stored in the Function CR spec.
When deploying to a private registry, resolve credentials via the existing CredentialsProvider, create a docker-registry K8s Secret, and set .spec.registry.authSecretRef on the Function CR so the func-operator can authenticate with the registry.
- Check return value of AddToScheme (errcheck lint) - Make registry secret creation injectable for unit tests - Add git commit author in resolver tests for CI - Add FuncOperator to component-versions test expectations
ba2e1c9 to
38650ee
Compare
|
rebased and resolved merge conflicts |
Replace the CLI-level postDeploy hook with a FunctionSyncer interface in pkg/functions, implemented by pkg/operator.Syncer. This makes operator management available to all library users, not just the CLI. - Add FunctionSyncer interface and WithSyncer option to Client - Add ManagementDisabled field to DeploySpec (managed by default) - Create pkg/operator/syncer.go encapsulating git/registry resolution - Wire operator.NewSyncer in cmd/client.go NewClient() - Replace --manage flag with --management-disabled - Remove postDeploy hook, syncFunctionCR from cmd/deploy.go - Update integration test to use WithSyncer
A user deploying without a git remote is an expected base case, not a warning-worthy condition. The operator sync now requires both the CRD to be installed and a git URL to be available before attempting to create or update a Function CR.
Previously all errors from ServerResourcesForGroupVersion were swallowed and treated as "CRD not present". Now only NotFound errors are treated as CRD absence; other errors are propagated so legitimate failures are not silently ignored.
Merge the separate status-name and metadata-name lookups into a single pass over the list. Status name match still takes priority and returns immediately; metadata name match is remembered as a fallback.
Replace the hardcoded "functions.dev/v1alpha1" string with v1alpha1.GroupVersion.String() in hasFunctionCRD, unit tests, and integration test helper.
Update generated docs to reflect --manage being replaced by --management-disabled.
Add ManagementDisabled field to the generated schema.
|
Thanks for the review @lkingland Only maybe one thing we could also address in this PR: WDYT about removing the CR when |
Changes
func deploywhen func-operator is installedfunc deploy --management-disabledcontroller-runtimedependency)/kind enhancement
Release Note